#include "e2d/core/Scene.h"

#include "e2d/ui/SceneTreeNodeEditor.h"
#include "e2d/ui/Layout.h"
#include "e2d/ui/Utils.h"

using namespace fxcc::platform;
using namespace fxcc::graph;
using namespace fxcc::graph::opengl3;
using namespace fxcc::imgui::graph::opengl3;
using BaseApp = fxcc::imgui::graph::opengl3::GlfwApp;

#undef main

extern "C" {
    __declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
}

struct SimpleApp : public BaseApp
{
public:

    std::shared_ptr<e2d::Layout> m_Layout;

    e2d::Timer m_e2dTimer;

    glm::vec4 color;

    SimpleApp(const fxcc::platform::common::App::Desc& desc) : BaseApp(desc), color(1.0)
    {
    }
    bool Init() override
    {
        if (!BaseApp::Init())
        {
            return false;
        }

        if (!InitResources())
        {
            ztclog::info("failed init the resources");
            return false;
        }

#ifdef _WIN32
        ImGuiIO& io = ImGui::GetIO();
        ImFont* font = io.Fonts->AddFontFromFileTTF("C:/Windows/Fonts/simhei.ttf", 25.0f, nullptr, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
        //ImFont* font = io.Fonts->AddFontFromFileTTF("C:/Windows/Fonts/msyh.ttc", 25.0f, nullptr, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
#endif
#ifdef __linux__

#endif

        return true;
    };

    bool InitResources()
    {
        // load asserts if has not load ;recode data into the metapath
        e2d::Utils::LoadMetaCache();
        
        // increment Import the data
        //e2d::Utils::SetLibraryPath("Library");
        e2d::Utils::ImportDirectory(fxcc::Dir("Assert"));
        e2d::Utils::SaveMetaCache();
        e2d::Utils::LoadMetaCache();

        // load resource loader
        e2d::Utils::InitLoader();
        fxcc::Dir _Lib_Dir("Library");
        fxcc::Dir _Assert_Dir("Assert");

        // Load library (dir)
        //e2d::Utils::LoadDirectory(_Lib_Dir);
        e2d::Utils::LoadShaderDir(_Assert_Dir);
        e2d::Utils::LoadRealMaterial(_Assert_Dir);

        // load game manager 
        e2d::Utils::InitGameManager();

        // getLast load scene
        e2d::Utils::LoadLastInstance();
        e2d::Utils::SetSceneFromInst();


        m_Layout = std::make_shared<e2d::Layout>();
        m_Layout->SetScene(e2d::Utils::m_Inst.m_Scene);

        m_e2dTimer.Start();

        return true;
    };

    fxcc::imgui::Editor editor;

    void OnEdit() override
    {
        m_Layout->Inst();

    }

    void OnDestroy() override
    {
        e2d::Utils::OnDestroy();
        e2d::Utils::OnSaveData();
        BaseApp::OnDestroy();
    }

    void OnFrameRender() override
    {

        glViewport(0, 0, m_Desc.m_Size.x, m_Desc.m_Size.y);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        e2d::Utils::OnRenderFrame();
    };

    void OnClose() override
    {
        m_Layout->OnDestroy();

        e2d::Utils::OnDestroy();
        e2d::Utils::OnSaveData();
        BaseApp::OnClose();
    }

    void OnFramebuffersize(int w, int h) override
    {
        opengl3::GlfwApp::OnFramebuffersize(w, h);

        //if (m_Layout)
        //    m_Layout->OnFramebuffersize(glm::ivec2(w, h));

        e2d::Utils::m_GameManager.OnFramebuffersize({ w, h });
    }

    void OnUpdate() override
    {
        opengl3::GlfwApp::OnUpdate();

        m_e2dTimer.Tick();
        m_Layout->Handle();

        e2d::Utils::m_Inst.m_Scene->SetTimerAndInput(&m_e2dTimer, &m_Input);
        e2d::Utils::m_Inst.m_AnimationScene->SetTimerAndInput(&m_e2dTimer, &m_Input);
        e2d::Utils::m_Inst.m_PrefebScene->SetTimerAndInput(&m_e2dTimer, &m_Input);

        auto& gm = e2d::Utils::m_GameManager;
        gm.SetTimerAndInput(&m_e2dTimer, &m_Input);
        gm.OnUpdate();
        gm.OnUpdateRuntime();



    }
};

int main()
{
    ztclog::pushFunction([](const ztclog::Line& line)
        {
            if (line.m_Type != ztclog::Line::Type::_line_debug_)
            {
                std::cout << line.m_Text << std::endl;
            } });

            using _App = SimpleApp;
            using _Desc = fxcc::platform::common::App::Desc;

            _Desc desc;
            desc.m_Pos = glm::ivec2(100, 100);
            desc.m_Size = glm::ivec2(1200, 900);
            desc.m_ScaleFactor = 1.0f;

            desc.m_Title = "e2d engine editor";
            std::shared_ptr<_App> _app = std::make_shared<_App>(desc);
            return _app->Run();
};
